<?php
namespace app\common\utils;

class CurrencyConverter
{
    /**
     * 人民币大写转数字
     * @param string $cnyStr 大写金额（如「壹万贰仟叁佰肆拾伍元整」）
     * @return string 数字金额（如「12345.00」）
     * @throws \InvalidArgumentException
     */
    public static function cnyToUpperToNumber(string $cnyStr): string
    {
        // 映射表
        $digitMap = [
            '零' => 0, '壹' => 1, '贰' => 2, '叁' => 3, '肆' => 4,
            '伍' => 5, '陆' => 6, '柒' => 7, '捌' => 8, '玖' => 9,
        ];
        $unitMap = [
            '分' => -2, '角' => -1, '元' => 0,
            '拾' => 1, '佰' => 2, '仟' => 3,
            '万' => 4, '亿' => 8,
        ];

        // 清理输入
        $cleanStr = str_replace([' ', '整'], '', $cnyStr);
        if (empty($cleanStr)) {
            throw new \InvalidArgumentException('输入的大写金额为空');
        }

        // 分割整数和小数部分
        $integerPart = '';
        $decimalPart = 0.0;
        if (strpos($cleanStr, '元') !== false) {
            list($integerPart, $rest) = explode('元', $cleanStr, 2);
            // 处理角、分
            if (strpos($rest, '角') !== false) {
                list($jiaoStr, $fenStr) = explode('角', $rest, 2);
                $decimalPart += $digitMap[$jiaoStr] * 0.1;
                if (strpos($fenStr, '分') !== false) {
                    $fenStr = explode('分', $fenStr)[0];
                    $decimalPart += $digitMap[$fenStr] * 0.01;
                }
            } elseif (strpos($rest, '分') !== false) {
                $fenStr = explode('分', $rest)[0];
                $decimalPart += $digitMap[$fenStr] * 0.01;
            }
        } else {
            $integerPart = $cleanStr;
        }

        // 解析整数部分
        $total = 0;
        $current = 0;
        $prevUnit = 0;
        $chars = str_split(strrev($integerPart)); // 反转后从低位到高位处理
        foreach ($chars as $char) {
            if (!isset($digitMap[$char]) && !isset($unitMap[$char])) {
                throw new \InvalidArgumentException("非法字符：{$char}");
            }

            if (isset($digitMap[$char])) {
                $current += $digitMap[$char] * pow(10, $prevUnit);
            } elseif (isset($unitMap[$char])) {
                $unit = $unitMap[$char];
                if ($unit > $prevUnit) {
                    $total += $current * pow(10, $unit - $prevUnit);
                    $current = 0;
                } else {
                    $current = $current ? $current * pow(10, $unit - $prevUnit) : pow(10, $unit);
                }
                $prevUnit = $unit;
            }
        }
        $total += $current;

        // 合并小数
        $result = $total + $decimalPart;
        return number_format($result, 2, '.', '');
    }
}